Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Async WebServices που χρησιμοποιούν WebRequest

Îåêßíçóå áðü ôï ìÝëïò flougr. Τελευταία δημοσίευση από το μέλος anjelinio στις 08-11-2007, 18:59. Υπάρχουν 3 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  08-11-2007, 15:36 37084

    Async WebServices που χρησιμοποιούν WebRequest

    Καλησπέρα , θα ήθελα τη γνώμη σας για το πώς πρέπει (και το αν πρεπει) να υλοποιηθεί ασύγχρονα ένα σύνολο ενεργείων που εκτελείτε στο background μιας ASP.NET 2 εφαρμογής.
    Συγκεκριμένα :

    Έχω κάνει register ένα HTTP Module το οποίο δημιουργεί ένα Thread και καλέι μια ρουτινα σε τακτικά χρονικά διαστήματα.

    Public Class CSBkGroundWorker
    Implements IHttpModule
      

     

    Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.InitDim t As New Thread(AddressOf SendMessages)

    Dim t As New Thread(AddressOf SendScheduledMessages)
    t.Start()

    End Sub

    ' Και η Sub την οποία τρέχει(Βρισκεται μεσα στο Module)
    Public Shared Sub SendScheduledMessages()


    While 1

    Dim MessageQueque As List(Of Messages) = New List(Of Messages)
    Dim MyWebService As New MyNameSpace.WebServices.Messaging

    MessageQueque=GetMessagesFromDataBase() ' Database Read

    For Each Msg in MessageQueque

    MyWebService.SendMessage(Msg) ' WebService Call

    LogMessageToDataBase(Msg)   ' Database Write



    Next

    Thread.Sleep(intervalminutes * 60000)


    End While



    End Sub

    Η Παραπάνω υπορουτίνα κάνει τα εξης (Εχω απλοποιήσει το κώδικα για λόγους εμφάνισης) :

    1. Δίαβάζει ενα σύνολο μηνυμάτων απο την βάση

    2. Για κάθε μήνυμα :

       2.a : Καλεί μια μέθοδο ενος Web Service η οποία στέλνει το μήνυμα σε κάποιο άλλο server κανοντας χρήση WebRequest (Synchronous)
       2.b : Γράφει σε εναν πίνακα Log της βάσης το αποτέλεσμα που επέστρεψε το Web Service

    3. Τελειώνοντας κανει Sleep το Thread για καποιο χρονικο διάστημα.

     

    Τέλος η Μεθοδος του WebService που καλέιται είναι περίπου η εξης :

    <WebMethod(MessageName:="SendMessage")> _
    Public Sub SendMessage( ByRef message As Messsage)

    Dim request As HttpWebRequest
    Dim response As HttpWebResponse = Nothing

    Dim reader As StreamReader


    Dim returnHttpResponseInfo As New MessageResponseInfo


    Try
    returnHttpResponseInfo.Status = MessageResponseInfo.StatusEnum.StatusUNKNOWN


    request = DirectCast(WebRequest.Create(message.address), HttpWebRequest)   ' To message.address ειναι ενα url σε απομακρυσμένο server 
    request.UserAgent = "MessageService"
    request.KeepAlive = False
    request.Timeout = RequestTimeoutSeconds * 1000

    ' Get response
    response = DirectCast(request.GetResponse(), HttpWebResponse)
    message.result=response

    End Sub

    Επειδή δέν εχω ξαναδουλέψει σε ασύγχρονα patterns θα ήθελα τη γνώμη σας στα εξης :

    a) Υπάρχει λόγος να γίνει η όλη διαδικασία ασύγχρονη ; Το Web Service κάνει WebRequests σε απομακρυσμένους server ειτε επειδη κλείθηκε απο το HTTPModule  είτε ως αποτελεσμα μιας ενεργειας των χρηστών της εφαρμογης (δηλαδή μπορει να χρειαστει να κληθει οποιαδήποτε στιγμη απο έναν η περρισοτερους χρήστες) .Αν την ώρα που το WebService εκτελεί μια σειρά απο WebRequest (Λογω κλησης του απο το HTTP Module)  , και ένας χρήστης εκτελέσει μια ενεργεια που εμπλέκει το webservice , θα χρειαστεί να περιμένει να τελείωσουν τα WebRequest απο το HTTP Module ; Η Επειδή το HttpModule τρέχει σε δικό του Thread , δεν χρειάζεται ;

    b) Αν χρειάζεται να γίνει η όλη διαδικασία ασυγχρονη τότε πως θα πρέπει να υλοποιηθεί αυτο ;

          1. Να γίνει όλη η Ρουτίνα SendScheduledMessages μέρος του WebService και να την καλώ Ασύγχρονα (BeginSendScheduledMessages...EndSendScheduledMessages) απο το HttpModule
          2. Να γινει  η κλήση της WebMethod SendMessage ασυγχρονη ; 
          3. Να αλλάξει η υλοποιηση της SendMessage και να κάνω τα WebRequest ασυγχρονα ;
          4. Όλα τα παραπάνω ; 

     

    Ευχαριστώ και ελπίζω να μην σας μπέρδεψα


     


     

     


       

     

  •  08-11-2007, 16:23 37088 σε απάντηση της 37084

    Απ: Async WebServices που χρησιμοποιούν WebRequest

    Το πρώτο που θα πώ είναι ... γιατί HttpModule ??? Νομίζω ότι αν πάρεις αυτόν τον κώδικα σε μια άλλη κλάσση, δημιουργώντας ένα singleton στο Application.OnStart μέσα στο Global.asax θα κάνεις πιο καθαρά τη δουλειά σου, τα HttpModules δεν είναι για αυτό το πράγμα που κάνεις, εφ'όσον στην ουσία δεν κάνεις respond σε events του Application. Ακόμα, ένα Windows Service, είναι πιο ταιριαστό σε αυτό που θες να κάνεις.

    ( Επίσης δεν έχεις "εύκολο" τρόπο να το "βρείς" απο κώδικα και να το σταματήσεις ... ενώ αν το σώσεις σε ένα Application.Items["mybackgroundMessageSender"] το βρίσκεις πολύ εύκολα και γρήγορα )

    Τώρα, όσον αφορά το asynchronicity. Στη μεριά του site, νομίζω ότι είσαι οκ έχοντας σαν δεδομένο ότι τρέχεις στο background, και δεν υπάρχει κάποιο ιδιέταιρο interaction μεταξύ του sender και του site, και αν τελικά δε σε νοιάζει πόσο χρόνο θα κάνει να τελειώσει με τα send.

    Στη μεριά του Web Service τώρα. Αν θυμάμαι καλά, τα web services είναι by default multi-instance. Δημιουργείται δηλαδή κάθε φορά που το καλείς ένα νέο instance. Οπότε, αυτό που σε καίει μόνο είναι το μέγεθος του ASP.NET Thread Pool. Αν όμως έχεις τόσο μεγάλο αριθμό χρηστών ώστε αυτό να γίνει όντως πρόβλημα, τότε ναι, κάνεις τη διαδικασία με τα Web Requests ασύγχρονα, βγάζοντάς την έξω απο τη SendMessage σε άλλο method, το οποίο θα εκτελέσεις σε νέο thread, ή θα καλέσεις ασύγχρονα - προσοχή, εκεί θα μπλέξει το πράγμα, για αρχή δοκίμασε απλώς το νέο thread. Αν φτάσεις το thread pool στα όριά του, θα πρέπει να "μετακομίσεις" σε κάποιο άλλο thread pool implementation, αλλιώς θα κλέβεις threads έτσι κι αλλιώς απο αυτό του ASP.NET, δώρον άδωρον  ...

    Ενδεικτικά να πώ ότι χρειάζεσαι  π ρ α γ μ α τ ι κ ά  μεγάλο αριθμό χρηστών για να φτάσεις το thread pool στα όριά του, αλλά μπορεί να γίνει. Μιλάμε όμως για χιλιάδες, όχι εκατοντάδες χρήστες.

    Angel
    O:]
  •  08-11-2007, 18:49 37109 σε απάντηση της 37088

    Απ: Async WebServices που χρησιμοποιούν WebRequest

    Καταρχήν ευχαριστώ για την απάντηση.
    Το Windows Service θα ηταν οντως η καλύτερη λύση αλλά είμαι σε Hosted Environment και ετσι αυτό δεν γίνεται.

    Σχετικά με το Thread Pool , νομίζω οτι δέν είναι πολύ δύσκολο να το φτάσω στα όρια του στη συγκεκριμενη περίπτωση.
    Παρόλο που δεν υπολογίζω να έχω πάνω απο 50-100 χρηστές online , υπάρχει περίπτωση να πρέπει να στειλώ πάνω απο 100 scheduled messages κάποια χρονική στιγμή.
    Εχω υπολογίσει οτι για να σταλεί κάθε μήνημα με το WebRequest και να πάρω το response , χρειάζoνται απο 4-6 δευτερόλεπτα και σε αυτά θα πρέπει να προσθεθούν αλλά 2 περίπου για την επεξεργασία και την εγγραφή του αποτελέσματος στη βαση.
    Ετσι αν πάρουμε ως παράδειγμα το 100 μηνύματα που θα πρέπει να φύγουν το ένα μετα το αλλο , θα χρειαστώ περίπου 10 λεπτά , στη καλύτερη περίπτωση , για να ολοκληρωθεί η διαδικασία.
    Αν έκανα τη διαδικασία ασυγχρονη , φοβάμαι οτι θα ανοιγανε πολλά νεα thread με αποτέλεσμα να φτάσει το thread pool στα ορία του , ειδικά απο τη στιγμή που είμαι σε hosted environment.

    Αυτό που με απασχολεί πιο πολύ είναι τι γίνεται αν κατα τη διάρκεια που στέλνονται αυτά τα 100 μηνύματα σειριακά (χωρις ασυγχρονες κλήσεις) συμβει καποιοι χρήστες να καλέσουν μεσα απο το UI της σελίδας το webservice για να στείλουν καποια μηνυματα.
    Θα πρέπει να περιμένουν να τελειώσουν τα WebRequest που εκτελούνται ηδη ή θα ξεκινήσει ένα νεο WebRequest για κάθε χρήστη σε άλλο Thread ;


     

     

  •  08-11-2007, 18:59 37111 σε απάντηση της 37109

    Απ: Async WebServices που χρησιμοποιούν WebRequest

    Άν δεν κάνω λάθος, μόνο ένα thread θα απασχοληθεί με το 10-λεπτο send operation.

    "Παράλληλες/ταυτόχρονες" κλήσεις στο ίδιο Web Service θα εκτελεστούν απο διαφορετικό instance, σε διαφορετικό thread. Μή μασάς λοιπόν.
    ( κατ' αρχήν ... έχεις γράψει κάποιο test το οποίο ανοίγει μερικούς clients που στέλνουν παράλληλα μυνήματα;;; Οτιδήποτε άλλο είναι λόγια στον αέρα ... )

    Αν κάνεις ασύγχρονη την αποστολή ολόκληρου του "πακέτου" μηνυμάτων μέσα στο Web Service, τότε θα ξεκινήσει ένα thread το οποίο θα "παίζει" μέχρι να στείλει τα 100 μηνύματα. Εν τω μεταξύ όμως, το Web Service method σου θα έχει "γυρίσει", δε θα μπλοκάρει, ελευθερώνοντάς σου έτσι ακόμη ένα instance του web service για τους callers σου. Διαφορά θα δείς όμως μετά τους 1000 απόλυτα παράλληλους χρήστες.

    Angel
    O:]
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems